home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / ds3100.md / machCode.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  58KB  |  2,071 lines

  1. /* 
  2.  * machCode.c --
  3.  *
  4.  *         C code for the mach module.
  5.  *
  6.  *    Copyright (C) 1989 Digital Equipment Corporation.
  7.  *    Permission to use, copy, modify, and distribute this software and
  8.  *    its documentation for any purpose and without fee is hereby granted,
  9.  *    provided that the above copyright notice appears in all copies.  
  10.  *    Digital Equipment Corporation makes no representations about the
  11.  *    suitability of this software for any purpose.  It is provided "as is"
  12.  *    without express or implied warranty.
  13.  */
  14.  
  15. #ifndef lint
  16. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/mach/ds3100.md/machCode.c,v 9.27 92/08/10 17:58:15 mgbaker Exp $ SPRITE (DECWRL)";
  17. #endif not lint
  18.  
  19. #include <sprite.h>
  20. #include <stddef.h>
  21. #include <assert.h>
  22.  
  23. #include <machConst.h>
  24. #include <machMon.h>
  25. #include <machInt.h>
  26. #include <mach.h>
  27. #include <sys.h>
  28. #include <sync.h>
  29. #include <dbg.h>
  30. #include <proc.h>
  31. #include <procMigrate.h>
  32. #include <procUnixStubs.h>
  33. #include <sched.h>
  34. #include <vm.h>
  35. #include <vmMach.h>
  36. #include <sig.h>
  37. #include <sigMach.h>
  38. #include <swapBuffer.h>
  39. #include <net.h>
  40. #include <ultrixSignal.h>
  41. #include <recov.h>
  42.  
  43. /*
  44.  * Conversion of function to an unsigned value.
  45.  */
  46. #define F_TO_A    (Address)(unsigned)(int (*)())
  47. /*
  48.  *  Number of processors in the system.
  49.  */
  50. #ifndef NUM_PROCESSORS
  51. #define NUM_PROCESSORS 1
  52. #endif
  53.  
  54. int mach_NumProcessors = NUM_PROCESSORS;
  55.  
  56. /*
  57.  * TRUE if cpu was in kernel mode before the interrupt, FALSE if was in 
  58.  * user mode.
  59.  */
  60. Boolean    mach_KernelMode;
  61.  
  62. /*
  63.  *  Flag used by routines to determine if they are running at
  64.  *  interrupt level.
  65.  */
  66. Boolean mach_AtInterruptLevel = FALSE;
  67.  
  68. /*
  69.  * The machine type string is imported by the file system and
  70.  * used when expanding $MACHINE in file names.
  71.  */
  72.  
  73. char *mach_MachineType = "ds3100";
  74.  
  75. extern int debugProcStubs;
  76.  
  77. /*
  78.  * The byte ordering/alignment type used with Fmt_Convert and I/O control data
  79.  */
  80. Fmt_Format mach_Format = FMT_MIPS_FORMAT;
  81.  
  82. /*
  83.  *  Count of number of ``calls'' to enable interrupts minus number of calls
  84.  *  to disable interrupts.  Kept on a per-processor basis.
  85.  */
  86. int mach_NumDisableInterrupts[NUM_PROCESSORS];
  87. int *mach_NumDisableIntrsPtr = mach_NumDisableInterrupts;
  88.  
  89. /*
  90.  * The format that the kernel stack has to be in to start a process off.
  91.  */
  92. typedef struct {
  93.     int        magicNumber;        /* Magic number used to determine if
  94.                      * the stack has been corrupted. */
  95.     int        statusReg;        /* The status register value. */
  96.     int        filler[10];        /* Extra space on the stack to
  97.                      * store args and such. */
  98. } KernelStack;
  99.  
  100. /*
  101.  * The format of a signal stack that is pushed onto a user's stack when
  102.  * a signal is handled.
  103.  */
  104. typedef struct {
  105.     Sig_Stack    sigStack;
  106.     Sig_Context    sigContext;
  107. } SignalStack;
  108.  
  109. /*
  110.  * Machine dependent variables.
  111.  */
  112. Address    mach_KernStart;
  113. Address    mach_CodeStart;
  114. Address    mach_StackBottom;
  115. int    mach_KernStackSize;
  116. Address    mach_KernEnd;
  117. Address    mach_FirstUserAddr;
  118. Address    mach_LastUserAddr;
  119. Address    mach_MaxUserStackAddr;
  120. int    mach_LastUserStackPage;
  121.  
  122. /*
  123.  * The variables and tables below are used to dispatch kernel calls.
  124.  */
  125.  
  126. #define MAXCALLS 120
  127. #define MAXARGS  10
  128.  
  129. int machMaxSysCall;            /* Highest defined system call. */
  130. /*
  131.  * Tables to determine where to go to fetch the arguments for a system call.
  132.  */
  133. ReturnStatus (*machArgDispatch[MAXCALLS])();
  134. ReturnStatus (*machArgDispatchTable[])() = {
  135.     MachFetch0Args,
  136.     MachFetch0Args,
  137.     MachFetch0Args,
  138.     MachFetch0Args,
  139.     MachFetch0Args,
  140.     MachFetch1Arg,
  141.     MachFetch2Args,
  142.     MachFetch3Args,
  143.     MachFetch4Args,
  144.     MachFetch5Args,
  145.     MachFetch6Args,
  146. };
  147.  
  148. ReturnStatus (*(mach_NormalHandlers[MAXCALLS]))();
  149.                     /* For each system call, gives the
  150.                      * address of the routine to handle
  151.                      * the call for non-migrated processes.
  152.                      */
  153. ReturnStatus (*(mach_MigratedHandlers[MAXCALLS]))();
  154.                     /* For each system call, gives the
  155.                      * address of the routine to handle
  156.                      * the call for migrated processes. */
  157. int machKcallTableOffset;        /* Byte offset of the kcallTable field
  158.                      * in a Proc_ControlBlock. */
  159. int machStatePtrOffset;            /* Byte offset of the machStatePtr
  160.                      * field in a Proc_ControlBlock. */
  161. int machSpecialHandlingOffset;        /* Byte offset of the specialHandling
  162.                      * field in a Proc_ControlBlock. */
  163. MachStringTable    machMonBootParam;    /* Parameters from boot line. */
  164. /* 
  165.  * Pointer to the state structure for the current process and the
  166.  * current owner of the floating point unit.
  167.  */
  168. Mach_State    *machCurStatePtr = (Mach_State *)NIL;
  169. Mach_State    *machFPCurStatePtr = (Mach_State *)NIL;
  170.  
  171. extern Boolean Dev_SIIIntr();
  172. extern void Timer_TimerServiceInterrupt();
  173. extern void Dev_DC7085Interrupt();
  174. extern void MachFPInterrupt();
  175.  
  176. extern void PrintError _ARGS_((void));
  177. static void PrintInst _ARGS_((unsigned pc, unsigned inst));
  178. static void SoftFPReturn _ARGS_((void));
  179. static void MemErrorInterrupt _ARGS_((void));
  180. static void CheckFastRestart _ARGS_((void));
  181.  
  182. /*
  183.  * The interrupt handler table. This originally was static, hence the
  184.  * initialization here.  It is now possible to set the entries
  185.  * via Mach_SetHandler().
  186.  */
  187. void (*machInterruptRoutines[MACH_NUM_HARD_INTERRUPTS])() = {
  188.     (void (*)())Dev_SIIIntr,
  189.     (void (*)())Net_Intr,
  190.     Dev_DC7085Interrupt,
  191.     Timer_TimerServiceInterrupt,
  192.     MemErrorInterrupt,
  193.     MachFPInterrupt,
  194. };
  195.  
  196. ClientData    machInterruptArgs[MACH_NUM_HARD_INTERRUPTS];
  197.  
  198. extern void Mach_KernGenException();
  199. extern void Mach_UserGenException();
  200. extern void VmMach_KernTLBException();
  201. extern void VmMach_TLBModException();
  202. extern void VmMach_UTLBMiss();
  203. extern void VmMach_EndUTLBMiss();
  204.  
  205. /*
  206.  * The kernel exception handlers.
  207.  */
  208. void (*machKernExcTable[])() = {
  209.     Mach_KernGenException,
  210.     VmMach_TLBModException,
  211.     VmMach_KernTLBException,
  212.     VmMach_KernTLBException,
  213.     Mach_KernGenException,
  214.     Mach_KernGenException,
  215.     Mach_KernGenException,
  216.     Mach_KernGenException,
  217.     Mach_KernGenException,
  218.     Mach_KernGenException,
  219.     Mach_KernGenException,
  220.     Mach_KernGenException,
  221.     Mach_KernGenException,
  222. };
  223.  
  224. /*
  225.  * The kernel exception handlers.
  226.  */
  227. void (*machUserExcTable[])() = {
  228.     Mach_UserGenException,
  229.     VmMach_TLBModException,
  230.     Mach_UserGenException,
  231.     Mach_UserGenException,
  232.     Mach_UserGenException,
  233.     Mach_UserGenException,
  234.     Mach_UserGenException,
  235.     Mach_UserGenException,
  236.     MachSysCall,
  237.     Mach_UserGenException,
  238.     Mach_UserGenException,
  239.     Mach_UserGenException,
  240.     Mach_UserGenException,
  241. };
  242.  
  243. /*
  244.  * Size of the instruction and data caches.
  245.  */
  246. unsigned    machDataCacheSize;
  247. unsigned    machInstCacheSize;
  248.  
  249. /*
  250.  * The debugger structure.
  251.  */
  252. Mach_DebugState    mach_DebugState;
  253. Mach_DebugState *machDebugStatePtr = &mach_DebugState;
  254.  
  255. static void SetupSigHandler _ARGS_((register Proc_ControlBlock *procPtr, 
  256.             register SignalStack *sigStackPtr, Address pc));
  257. static void ReturnFromSigHandler _ARGS_((register Proc_ControlBlock *procPtr));
  258. static ReturnStatus Interrupt _ARGS_((unsigned statusReg, unsigned causeReg, 
  259.             Address pc));
  260.  
  261. /*
  262.  * Preallocate all machine state structs.
  263.  */
  264. Mach_State    machStateTable[VMMACH_MAX_KERN_STACKS];
  265. int        nextStateIndex = 0;
  266.  
  267. /*
  268.  *  Save the bad address that caused an exception. This makes debugging
  269.  *  of TLB misses easier.
  270.  */
  271.  
  272. Address        machBadVaddr = (Address) NIL;
  273.  
  274. /*
  275.  * Declarations of recovery-related items.  For the decstations, most
  276.  * of these are no-ops.
  277.  *
  278.  * The following two variables should be in the initialized ata space, but
  279.  * marked as not initialized.  Then , when they are updated as part of booting,
  280.  * their new values get preserved over a fast restart.
  281.  */
  282. int     storedDataSize = -1;            /* Not initialized. */
  283. char    *mach_RestartTablePtr = (char *) NIL;
  284. char    storedData[1];                  /* A no-op for now. */
  285.  
  286. /*
  287.  * ----------------------------------------------------------------------------
  288.  *
  289.  * Mach_Init --
  290.  *
  291.  *    Initialize the exception vector table and some of the dispatching
  292.  *    tables.
  293.  *
  294.  * Results:
  295.  *    None.
  296.  *
  297.  * Side effects:
  298.  *    The exception vector table is initialized.
  299.  *
  300.  * ----------------------------------------------------------------------------
  301.  */
  302. void
  303. Mach_Init(boot_argc,boot_argv)
  304. int    boot_argc;    /* Argc from boot sequence. */
  305. MachStringTable    *boot_argv;    /* Boot sequence strings. */
  306. {
  307.     extern char end[], edata[];
  308.     int offset, i;
  309.     char buf[256];
  310.  
  311.     /*
  312.      * Zero out the bss segment.
  313.      */
  314.     bzero(edata, end - edata);
  315.  
  316.     /*
  317.      * Set exported machine dependent variables.
  318.      */
  319.     mach_KernStart = (Address)MACH_KERN_START;
  320.     mach_KernEnd = (Address)MACH_KERN_END;
  321.     mach_CodeStart = (Address)MACH_CODE_START;
  322.     mach_StackBottom = (Address)MACH_STACK_BOTTOM;
  323.     mach_KernStackSize = MACH_KERN_STACK_SIZE;
  324.     mach_FirstUserAddr = (Address)MACH_FIRST_USER_ADDR;
  325.     mach_LastUserAddr = (Address)MACH_LAST_USER_ADDR;
  326.     mach_MaxUserStackAddr = (Address)MACH_MAX_USER_STACK_ADDR;
  327.     mach_LastUserStackPage = (MACH_MAX_USER_STACK_ADDR - 1) / VMMACH_PAGE_SIZE;
  328.  
  329.     /*
  330.      * Copy the boot parameter structure. The original location will get
  331.      * unmapped during vm initialization so we need to get our own copy.
  332.      * Depending on how the machine was booted, the boot arguments 
  333.      * may or may not be parsed.  So we'll glob them all together and
  334.      * then parse them.
  335.      */
  336.     buf[0] = '\0';
  337.     for (i = 0; i < boot_argc; i++) {
  338.     strcat(buf,boot_argv->argPtr[i]);
  339.     strcat(buf," ");
  340.     }
  341.     Mach_ArgParse(buf,&machMonBootParam);
  342.  
  343.     /*
  344.      * Initialize some of the dispatching information.  The rest is
  345.      * initialized by Mach_InitSysCall below.
  346.      */
  347.     machMaxSysCall = -1;
  348.     machKcallTableOffset = (int) &((Proc_ControlBlock *) 0)->kcallTable;
  349.     machStatePtrOffset = (int) &((Proc_ControlBlock *) 0)->machStatePtr;
  350.     machSpecialHandlingOffset = (int) 
  351.                 &((Proc_ControlBlock *) 0)->specialHandling;
  352.  
  353.     /*
  354.      * We start off with interrupts disabled.
  355.      */
  356.     mach_NumDisableInterrupts[0] = 1;
  357.  
  358.     /*
  359.      * Copy down exception vector code.
  360.      */
  361.     if (F_TO_A VmMach_EndUTLBMiss - F_TO_A VmMach_UTLBMiss > 0x80) {
  362.     panic("Mach_Init: UTLB code too large\n");
  363.     }
  364.     bcopy(F_TO_A VmMach_UTLBMiss, F_TO_A MACH_UTLB_MISS_EXC_VEC,
  365.         F_TO_A VmMach_EndUTLBMiss - F_TO_A VmMach_UTLBMiss);
  366.     bcopy(F_TO_A MachException, (Address)MACH_GEN_EXC_VEC,
  367.           F_TO_A MachEndException - F_TO_A MachException);
  368.  
  369.     if (recov_Transparent) {
  370.     CheckFastRestart();
  371.     }
  372.     /*
  373.      * Clear out the i and d caches.
  374.      */
  375.     Mach_MonPrintf("Configuring cache: ");
  376.     MachConfigCache();
  377.     Mach_MonPrintf("data cache size =%x inst cache size=%x\n",
  378.            machDataCacheSize, machInstCacheSize);
  379.     MachFlushCache();
  380. }
  381.  
  382. /*
  383.  * ----------------------------------------------------------------------------
  384.  *
  385.  * Mach_SetHandler --
  386.  *
  387.  *    Put a interrupt handling routine into the table.
  388.  *
  389.  * Results:
  390.  *     None.
  391.  *
  392.  * Side effects:
  393.  *     The interrupt handling table is modified.
  394.  *
  395.  * ----------------------------------------------------------------------------
  396.  */
  397.  
  398. void
  399. Mach_SetHandler(interruptNumber, handler, clientData)
  400.     int interruptNumber;    /* Interrupt number to set */
  401.     void (*handler)();    /* Interrupt handling procedure */
  402.     ClientData    clientData; /* ClientData for interrupt callback routine. */
  403. {
  404.     /*
  405.      * Check that it is valid.  Can't override FPU interrupt because it
  406.      * takes special parameters.
  407.      */
  408.     if ((interruptNumber < 0) || (interruptNumber >= MACH_NUM_HARD_INTERRUPTS)){
  409.     panic("Warning: Bad interrupt number %d\n",interruptNumber);
  410.     } else {
  411.     machInterruptRoutines[interruptNumber] = handler;
  412.     machInterruptArgs[interruptNumber] = clientData;
  413.     }
  414. }
  415.  
  416. static Vm_ProcInfo    mainProcInfo;
  417. static Mach_State    mainMachState;
  418. static VmMach_ProcData    mainProcData;
  419.  
  420. /*
  421.  *----------------------------------------------------------------------
  422.  *
  423.  * Mach_InitFirstProc --
  424.  *
  425.  *    Initialize the machine state struct for the very first process.
  426.  *
  427.  * Results:
  428.  *    None.
  429.  *
  430.  * Side effects:
  431.  *    Machine info allocated and stack start set up.
  432.  *
  433.  *----------------------------------------------------------------------
  434.  */
  435. void
  436. Mach_InitFirstProc(procPtr)
  437.     Proc_ControlBlock    *procPtr;
  438. {
  439.  
  440.     assert(offsetof(Proc_ControlBlock, unixErrno) == MACH_UNIX_ERRNO_OFFSET);
  441.     procPtr->machStatePtr = &mainMachState;
  442.     procPtr->machStatePtr->kernStackStart = mach_StackBottom;
  443.     procPtr->machStatePtr->kernStackEnd = 
  444.                 (mach_StackBottom + mach_KernStackSize);
  445.     /*
  446.      * Set up the TLB entries.  This code depends
  447.      * implictly upon MACH_KERN_STACK_PAGES.
  448.      */
  449.     procPtr->machStatePtr->tlbHighEntry  = 0;
  450.     procPtr->machStatePtr->tlbLowEntries[0] = 0;
  451.     procPtr->machStatePtr->tlbLowEntries[1] = 0;
  452.     procPtr->machStatePtr->tlbLowEntries[2] = 0;
  453.     procPtr->vmPtr = &mainProcInfo;
  454.     procPtr->vmPtr->machPtr = &mainProcData;
  455.     VmMach_ProcInit(&mainProcInfo);
  456.     machCurStatePtr = procPtr->machStatePtr;
  457.     VmMach_SetupContext(procPtr);
  458. }
  459.  
  460.  
  461. /*
  462.  *----------------------------------------------------------------------
  463.  *
  464.  * Mach_SetupNewState --
  465.  *
  466.  *    Initialize the machine state for this process.  This includes 
  467.  *    allocating and initializing a kernel stack.  Assumed that will
  468.  *    be called when starting a process after a fork or restarting a
  469.  *    process after a migration.
  470.  *
  471.  * Results:
  472.  *    PROC_NO_STACKS if couldn't allocate a kernel stack.  SUCCESS otherwise.
  473.  *
  474.  * Side effects:
  475.  *    Machine state in the destination process control block is overwritten.
  476.  *
  477.  *----------------------------------------------------------------------
  478.  */ 
  479. ReturnStatus
  480. Mach_SetupNewState(procPtr, fromStatePtr, startFunc, startPC, user)
  481.     Proc_ControlBlock    *procPtr;    /* Pointer to process control block
  482.                      * to initialize state for. */
  483.     Mach_State        *fromStatePtr;    /* State of parent on fork or from
  484.                      * other machine on migration. */
  485.     void        (*startFunc)();    /* Function to call when process first
  486.                      * starts executing. */
  487.     Address        startPC;    /* Address to pass as argument to 
  488.                      * startFunc.  If NIL then the address
  489.                      * is taken from *fromStatePtr's 
  490.                      * exception stack. */
  491.     Boolean        user;        /* TRUE if is a user process. */
  492. {
  493.     register    KernelStack    *stackPtr;
  494.     register    Mach_State    *statePtr;
  495.     unsigned            virtPage;
  496.  
  497.     if (procPtr->machStatePtr == (Mach_State *)NIL) {
  498.     procPtr->machStatePtr = &machStateTable[nextStateIndex];
  499.     nextStateIndex++;
  500.     if (nextStateIndex >= VMMACH_MAX_KERN_STACKS) {
  501.         panic("Mach_SetupNewState: Out of machine state structs\n");
  502.     }
  503.     }
  504.  
  505.     statePtr = procPtr->machStatePtr;
  506.     /* 
  507.      * Allocate a kernel stack for this process.
  508.      */
  509.     statePtr->kernStackStart = Vm_GetKernelStack(0);
  510.     if (statePtr->kernStackStart == (Address)NIL) {
  511.     return(PROC_NO_STACKS);
  512.     }
  513.     statePtr->kernStackEnd = statePtr->kernStackStart + MACH_KERN_STACK_SIZE;
  514.     /*
  515.      * Set up the TLB entries.  This code depends
  516.      * implictly upon MACH_KERN_STACK_PAGES.
  517.      */
  518.     virtPage = (unsigned)(statePtr->kernStackStart + VMMACH_PAGE_SIZE) >>
  519.                             VMMACH_PAGE_SHIFT;
  520.     statePtr->tlbHighEntry = (virtPage << VMMACH_TLB_VIRT_PAGE_SHIFT) |
  521.                  (VMMACH_KERN_PID << VMMACH_TLB_PID_SHIFT);
  522.     virtPage -= VMMACH_VIRT_CACHED_START_PAGE;
  523.     statePtr->tlbLowEntries[0] = vmMach_KernelTLBMap[virtPage];
  524.     statePtr->tlbLowEntries[1] = vmMach_KernelTLBMap[virtPage + 1];
  525.     statePtr->tlbLowEntries[2] = vmMach_KernelTLBMap[virtPage + 2];
  526.  
  527.     statePtr->switchRegState.regs[SP] =
  528.             (unsigned)(statePtr->kernStackEnd - sizeof(KernelStack));
  529.     /*
  530.      * Initialize the stack so that it looks like it is in the middle of
  531.      * Mach_ContextSwitch.
  532.      */
  533.     stackPtr = (KernelStack *)(statePtr->switchRegState.regs[SP]);
  534.     stackPtr->magicNumber = MAGIC;
  535.     stackPtr->statusReg = 0;
  536.     statePtr->switchRegState.regs[RA] = (unsigned)startFunc;
  537.     /*
  538.      * Set up the user's stack pointer.
  539.      */
  540.     statePtr->userState.regState.regs[SP] = (unsigned)mach_MaxUserStackAddr;
  541.     /* 
  542.      * Set up the state of the process.  User processes inherit from their
  543.      * parent or the migrated process.  If the PC is not specified, take it
  544.      * from the parent as well.
  545.      */
  546.     if (user) {
  547.     bcopy((Address)&fromStatePtr->userState,
  548.           (Address)&statePtr->userState,
  549.           sizeof(statePtr->userState));
  550.     statePtr->userState.regState.pc += 4;
  551.     }
  552.     if (startPC == (Address)NIL) {
  553.     statePtr->switchRegState.regs[A0] = 
  554.             (unsigned)fromStatePtr->userState.regState.pc + 4;
  555.     } else {
  556.     statePtr->switchRegState.regs[A0] = (unsigned)startPC;
  557.     }
  558.     statePtr->userState.regState.fpStatusReg = 0;
  559.  
  560.     return(SUCCESS);
  561. }
  562.  
  563. /*
  564.  *----------------------------------------------------------------------
  565.  *
  566.  * Mach_SetReturnVal --
  567.  *
  568.  *    Set the return value for a process from a system call.  Intended to
  569.  *    be called by the routine that starts a user process after a fork.
  570.  *
  571.  * Results:
  572.  *    None.
  573.  *
  574.  * Side effects:
  575.  *    Register D0 is set in the user registers.
  576.  *
  577.  *----------------------------------------------------------------------
  578.  */ 
  579. void
  580. Mach_SetReturnVal(procPtr, retVal, retVal2)
  581.     Proc_ControlBlock    *procPtr;    /* Process to set return value for. */
  582.     int            retVal;        /* Value for process to return. */
  583.     int            retVal2;    /* Second return value. */
  584. {
  585.     procPtr->machStatePtr->userState.regState.regs[V0] = (unsigned)retVal;
  586.     procPtr->machStatePtr->userState.regState.regs[V1] = (unsigned)retVal2;
  587. }
  588.  
  589. /*----------------------------------------------------------------------------
  590.  *
  591.  * Mach_Return2 --
  592.  *
  593.  *      Set the second return value for Unix compat. routines that
  594.  *      return two values.
  595.  *
  596.  * Results:
  597.  *      None.
  598.  *
  599.  * Side effects:
  600.  *      v1 <- val
  601.  *
  602.  *----------------------------------------------------------------------------
  603.  */
  604. void
  605. Mach_Return2(val)
  606. int val;
  607. {
  608.     Proc_GetActualProc()->machStatePtr->userState.regState.regs[V1] =
  609.         (unsigned)val;
  610. }
  611.  
  612. /*
  613.  *----------------------------------------------------------------------
  614.  *
  615.  * Mach_StartUserProc --
  616.  *
  617.  *    Start a user process executing for the first time.
  618.  *
  619.  * Results:
  620.  *    None.
  621.  *
  622.  * Side effects:
  623.  *    Stack pointer and the program counter set for the process and
  624.  *    the current process's image is replaced.
  625.  *
  626.  *----------------------------------------------------------------------
  627.  */
  628. void
  629. Mach_StartUserProc(procPtr, entryPoint)
  630.     Proc_ControlBlock    *procPtr;    /* Process control block for process
  631.                      * to start. */
  632.     Address        entryPoint;    /* Where process is to start
  633.                      * executing. */
  634. {
  635.     register    Mach_State    *statePtr;
  636.  
  637.     statePtr = procPtr->machStatePtr;
  638.     statePtr->userState.regState.pc = entryPoint;
  639.     (void)MachUserReturn(procPtr);
  640.  
  641.     MachRunUserProc(entryPoint, statePtr->userState.regState.regs[SP]);
  642.     /* THIS DOES NOT RETURN */
  643. }
  644.  
  645.  
  646. /*
  647.  *----------------------------------------------------------------------
  648.  *
  649.  * Mach_ExecUserProc --
  650.  *
  651.  *    Replace the calling user process's image with a new one.
  652.  *
  653.  * Results:
  654.  *    None.
  655.  *
  656.  * Side effects:
  657.  *    Stack pointer set for the process.
  658.  *
  659.  *----------------------------------------------------------------------
  660.  */
  661. void
  662. Mach_ExecUserProc(procPtr, userStackPtr, entryPoint)
  663.     Proc_ControlBlock    *procPtr;        /* Process control block for
  664.                          * process to exec. */
  665.     Address        userStackPtr;    /* Stack pointer for when the
  666.                          * user process resumes 
  667.                          * execution. */
  668.     Address        entryPoint;        /* Where the user process is
  669.                          * to resume execution. */
  670. {
  671.     procPtr->machStatePtr->userState.regState.regs[SP] =
  672.                         (unsigned)userStackPtr;
  673.     Mach_StartUserProc(procPtr, entryPoint);
  674.     /* THIS DOES NOT RETURN */
  675. }
  676.  
  677. /*
  678.  *----------------------------------------------------------------------
  679.  *
  680.  * Mach_FreeState --
  681.  *
  682.  *    Free up the machine state for the given process control block.
  683.  *
  684.  * Results:
  685.  *    None.
  686.  *
  687.  * Side effects:
  688.  *    Free up the kernel stack.
  689.  *
  690.  *----------------------------------------------------------------------
  691.  */
  692. void
  693. Mach_FreeState(procPtr)
  694.     Proc_ControlBlock    *procPtr;    /* Process control block to free
  695.                      * machine state for. */
  696. {
  697.     if (procPtr->machStatePtr->kernStackStart != (Address)NIL) {
  698.     Vm_FreeKernelStack(procPtr->machStatePtr->kernStackStart);
  699.     procPtr->machStatePtr->kernStackStart = (Address)NIL;
  700.     }
  701.     if (procPtr->machStatePtr == machFPCurStatePtr) {
  702.     machFPCurStatePtr = (Mach_State *)NIL;
  703.     }
  704. }
  705.  
  706.  
  707. /*
  708.  *----------------------------------------------------------------------
  709.  *
  710.  * Mach_CopyState --
  711.  *
  712.  *    Copy the state from the given state structure to the machine
  713.  *    state structure for the destination process control block.  Intended
  714.  *    to be used by the debugger to modify the state.The only fields
  715.  *    that can be modified are the following:
  716.  *
  717.  *        1) user stack pointer
  718.  *        2) all trap registers except for the stack pointer because the
  719.  *           stack pointer in the trap registers is the kernel stack pointer.
  720.  *        3) the PC, VOR and status register in the exception stack.
  721.  *
  722.  * Results:
  723.  *    None.
  724.  *
  725.  * Side effects:
  726.  *    Machine state in the destination process control block is overwritten.
  727.  *
  728.  *----------------------------------------------------------------------
  729.  */ 
  730. void
  731. Mach_CopyState(statePtr, destProcPtr)
  732.     Mach_State        *statePtr;    /* Pointer to state to copy from. */
  733.     Proc_ControlBlock    *destProcPtr;    /* Process control block to copy
  734.                      * state to. */
  735. {
  736.     bcopy((Address)&statePtr->userState,
  737.           (Address)&destProcPtr->machStatePtr->userState,
  738.           sizeof(statePtr->userState));
  739. }
  740.  
  741.  
  742. /*
  743.  *----------------------------------------------------------------------
  744.  *
  745.  * Mach_GetDebugState --
  746.  *
  747.  *    Extract the appropriate fields from the machine state struct
  748.  *    and store them into the debug struct.
  749.  *
  750.  * Results:
  751.  *    None.
  752.  *
  753.  * Side effects:
  754.  *    Debug struct filled in from machine state struct.
  755.  *
  756.  *----------------------------------------------------------------------
  757.  */ 
  758. void
  759. Mach_GetDebugState(procPtr, debugStatePtr)
  760.     Proc_ControlBlock    *procPtr;
  761.     Proc_DebugState    *debugStatePtr;
  762. {
  763.     register    Mach_State    *machStatePtr;
  764.  
  765.     machStatePtr = procPtr->machStatePtr;
  766.     bcopy((Address)machStatePtr->userState.regState.regs,
  767.           (Address)debugStatePtr->regState.regs,
  768.           sizeof(machStatePtr->userState.regState.regs));
  769.     debugStatePtr->regState.pc = machStatePtr->userState.regState.pc;
  770. }
  771.  
  772.  
  773. /*
  774.  *----------------------------------------------------------------------
  775.  *
  776.  * Mach_SetDebugState --
  777.  *
  778.  *    Extract the appropriate fields from the debug struct
  779.  *    and store them into the machine state struct.
  780.  *
  781.  * Results:
  782.  *    None.
  783.  *
  784.  * Side effects:
  785.  *    Machine state struct filled in from the debug state struct.
  786.  *
  787.  *----------------------------------------------------------------------
  788.  */ 
  789. void
  790. Mach_SetDebugState(procPtr, debugStatePtr)
  791.     Proc_ControlBlock    *procPtr;
  792.     Proc_DebugState    *debugStatePtr;
  793. {
  794.     register    Mach_State    *machStatePtr;
  795.  
  796.     machStatePtr = procPtr->machStatePtr;
  797.     bcopy((Address)debugStatePtr->regState.regs,
  798.           (Address)machStatePtr->userState.regState.regs,
  799.           sizeof(machStatePtr->userState.regState.regs));
  800.     machStatePtr->userState.regState.pc = debugStatePtr->regState.pc;
  801. }
  802.  
  803.  
  804. /*
  805.  * ----------------------------------------------------------------------------
  806.  *
  807.  * Mach_GetUserStackPtr --
  808.  *
  809.  *    Return the user stack pointer from the machine state struct for the
  810.  *    given process.
  811.  *
  812.  * Results:
  813.  *    The value of the user stack pointer when the process trapped.
  814.  *
  815.  * Side effects:
  816.  *    None.
  817.  *
  818.  * ----------------------------------------------------------------------------
  819.  */
  820. Address
  821. Mach_GetUserStackPtr(procPtr)
  822.     Proc_ControlBlock    *procPtr;
  823. {
  824.     return((Address)procPtr->machStatePtr->userState.regState.regs[SP]);
  825. }
  826.  
  827.  
  828. /*
  829.  * ----------------------------------------------------------------------------
  830.  *
  831.  * Mach_GetStackPointer --
  832.  *
  833.  *    Return the value of the stack pointer.
  834.  *
  835.  * Results:
  836.  *    The value of the user's stack pointer.
  837.  *
  838.  * Side effects:
  839.  *    None.
  840.  *
  841.  * ----------------------------------------------------------------------------
  842.  */
  843. Address
  844. Mach_GetStackPointer(procPtr)
  845.     Proc_ControlBlock    *procPtr;
  846. {
  847.     return((Address)procPtr->machStatePtr->userState.regState.regs[SP]);
  848. }
  849.  
  850.  
  851. /*
  852.  *----------------------------------------------------------------------
  853.  *
  854.  * Mach_InitSyscall --
  855.  *
  856.  *    During initialization, this procedure is called once for each
  857.  *    kernel call, in order to set up information used to dispatch
  858.  *    the kernel call.  This procedure must be called once for each
  859.  *    kernel call, in order starting at 0.
  860.  *
  861.  * Results:
  862.  *    None.
  863.  *
  864.  * Side effects:
  865.  *    Initializes the dispatch tables for the kernel call.
  866.  *
  867.  *----------------------------------------------------------------------
  868.  */
  869. void
  870. Mach_InitSyscall(callNum, numArgs, normalHandler, migratedHandler)
  871.     int callNum;            /* Number of the system call. */
  872.     int numArgs;            /* Number of one-word arguments passed
  873.                      * into call on stack. */
  874.     ReturnStatus (*normalHandler)();    /* Procedure to process kernel call
  875.                      * when process isn't migrated. */
  876.     ReturnStatus (*migratedHandler)();    /* Procedure to process kernel call
  877.                      * for migrated processes. */
  878. {
  879.     machMaxSysCall++;
  880.     if (machMaxSysCall != callNum) {
  881.     printf("Warning: out-of-order kernel call initialization, call %d\n",
  882.            callNum);
  883.     }
  884.     if (machMaxSysCall >= MAXCALLS) {
  885.     printf("Warning: too many kernel calls.\n");
  886.     machMaxSysCall--;
  887.     return;
  888.     }
  889.     if (numArgs > MAXARGS) {
  890.     printf("Warning: too many arguments to kernel call %d\n", callNum);
  891.     numArgs = MAXARGS;
  892.     }
  893.     machArgDispatch[machMaxSysCall] = machArgDispatchTable[numArgs];
  894.     mach_NormalHandlers[machMaxSysCall] = normalHandler;
  895.     mach_MigratedHandlers[machMaxSysCall] = migratedHandler;
  896. }
  897.  
  898.  
  899. /*
  900.  * ----------------------------------------------------------------------------
  901.  *
  902.  * MachUserExceptionHandler --
  903.  *
  904.  *      Handle a user exception.
  905.  *
  906.  * Results:
  907.  *      TRUE if should enable the floating point coprocessor.
  908.  *
  909.  * Side effects:
  910.  *      None.
  911.  *
  912.  * ----------------------------------------------------------------------------
  913.  */
  914. Boolean
  915. MachUserExceptionHandler(statusReg, causeReg, badVaddr, pc)
  916.     unsigned    statusReg;    /* The status register at the time of the
  917.                  * exception. */
  918.     unsigned    causeReg;    /* The cause register - contains the type
  919.                  * of exception. */
  920.     Address    badVaddr;    /* The address (if any) that the fault
  921.                  * occured on. */
  922.     Address    pc;        /* Program counter where to continue. */
  923. {
  924.     register    Proc_ControlBlock    *procPtr;
  925.     int                    cause;
  926.     Boolean                retVal;
  927.     ReturnStatus            status;
  928.  
  929.     machBadVaddr = badVaddr;
  930.     cause = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
  931.     if (cause != MACH_EXC_INT) {
  932.     Mach_EnableIntr();
  933.     }
  934.  
  935.     procPtr = Proc_GetActualProc();
  936.     switch (cause) {
  937.     case MACH_EXC_INT:
  938.         status = Interrupt(statusReg, causeReg, pc);
  939.         if (status != MACH_OK) {
  940.         panic("MachUserExceptionHandler: nested interrupts.\n");
  941.         }
  942.         /* 
  943.          * Enable interrupts so that we can do the user mode return
  944.          * checks.
  945.          */
  946.         Mach_EnableIntr();
  947.         break;
  948.     case MACH_EXC_TLB_MOD:
  949.         if (VmMach_TLBModFault(badVaddr) != SUCCESS) {
  950.         printf("Protection fault in process %x: pc=%x addr=%x\n",
  951.             procPtr->processID, pc, badVaddr);
  952.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  953.                 procPtr->processID, FALSE, badVaddr);
  954.         }
  955.         break;
  956.     case MACH_EXC_TLB_LD_MISS:
  957.     case MACH_EXC_TLB_ST_MISS:
  958.         if (VmMach_TLBFault(badVaddr) != SUCCESS) {
  959.         printf("Bad user TLB fault in process %x: pc=%x addr=%x\n",
  960.             procPtr->processID, pc, badVaddr);
  961.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  962.                 procPtr->processID, FALSE, badVaddr);
  963.         }
  964.         break;
  965.     case MACH_EXC_ADDR_ERR_LD:
  966.     case MACH_EXC_ADDR_ERR_ST:
  967.         printf("Address fault in process %x: pc=%x addr=%x\n",
  968.             procPtr->processID, pc, badVaddr);
  969.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  970.                 procPtr->processID, FALSE, badVaddr);
  971.         break;
  972.     case MACH_EXC_BUS_ERR_IFETCH:
  973.         printf("MachExceptionHandler: User bus error on ifetch");
  974.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  975.                 procPtr->processID, FALSE, badVaddr);
  976.         break;
  977.     case MACH_EXC_BUS_ERR_LD_ST:
  978.         printf("MachExceptionHandler: User bus error on ld or st");
  979.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  980.                 procPtr->processID, FALSE, badVaddr);
  981.         break;
  982.     case MACH_EXC_SYSCALL:
  983.         if (!MachUNIXSyscallNew()) {
  984.         printf("MachExceptionHandler: Bad syscall magic for proc %x\n",
  985.                             procPtr->processID);
  986.         (void) Sig_Send(SIG_ILL_INST, SIG_BAD_TRAP,
  987.                 procPtr->processID, FALSE, pc);
  988.         }
  989.         break;
  990.     case MACH_EXC_BREAK: {
  991.         unsigned inst;
  992.         /*
  993.          * Check to see if this is a return from signal handler
  994.          * break or a normal breakpoint.
  995.          */
  996.         if (Vm_CopyIn(sizeof(int), pc, (Address)&inst) != SUCCESS) {
  997.         panic("MachExceptionHandler: Couldn't fetch break inst.");
  998.         }
  999. #if 0
  1000.         printf("Pc = 0x%x, Instruction = 0x%x\n", pc, inst);
  1001.         printf("Cause register = 0x%x\n", causeReg);
  1002. #endif
  1003.         switch ((int)(inst & MACH_BREAK_CODE_FIELD)) {
  1004.         case MACH_BREAKPOINT_VAL:
  1005.             Proc_Lock(procPtr);
  1006.             if (procPtr->genFlags & PROC_DEBUG_ON_EXEC) {
  1007.             procPtr->genFlags &= ~PROC_DEBUG_ON_EXEC;
  1008.             (void) Sig_SendProc(procPtr, SIG_DEBUG, 
  1009.                         SIG_NO_CODE, pc);
  1010.             } else {
  1011.             (void) Sig_SendProc(procPtr, SIG_BREAKPOINT, 
  1012.                         SIG_NO_CODE, pc);
  1013.             }
  1014.             Proc_Unlock(procPtr);
  1015.             break;
  1016.         case MACH_SSTEP_VAL: {
  1017.             ReturnStatus    status;
  1018.  
  1019.             Vm_ChangeCodeProt(procPtr, pc, 4, TRUE);
  1020.             status = Vm_CopyOut(4, (Address)&machCurStatePtr->sstepInst,                    pc);
  1021.             Vm_ChangeCodeProt(procPtr, pc, 4, FALSE);
  1022.             Vm_FlushCode(procPtr, pc, 4);
  1023.             if (status != SUCCESS) {
  1024.             panic("MachUserExceptionHandler: Bad sstep PC\n");
  1025.             }
  1026.             Proc_Lock(procPtr);
  1027.             (void) Sig_SendProc(procPtr, SIG_TRACE_TRAP, SIG_NO_CODE,
  1028.                 pc);
  1029.             Proc_Unlock(procPtr);
  1030.             break;
  1031.         }
  1032.  
  1033.         case MACH_SIG_RET_VAL:
  1034.             ReturnFromSigHandler(procPtr);
  1035.             break;
  1036.         default:
  1037.             printf("Bogus bp-trap\n");
  1038.             (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1039.                     procPtr->processID, FALSE, pc);
  1040.             break;
  1041.         }
  1042.         break;
  1043.     }
  1044.     case MACH_EXC_RES_INST:
  1045.         printf("Reserved instruction in process %x at pc=%x\n",
  1046.             procPtr->processID, pc);
  1047.         (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1048.                 procPtr->processID, FALSE, pc);
  1049.         break;
  1050.     case MACH_EXC_COP_UNUSABLE:
  1051.         MachSwitchFPState(machFPCurStatePtr, machCurStatePtr);
  1052.         machFPCurStatePtr = machCurStatePtr;
  1053.         break;
  1054.     case MACH_EXC_OVFLOW:
  1055.         printf("Overflow exception in process %x at pc=%x\n",
  1056.             procPtr->processID, pc);
  1057.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_OVERFLOW,
  1058.                 procPtr->processID, FALSE, pc);
  1059.         break;
  1060.     }
  1061.     retVal = MachUserReturn(procPtr);
  1062.  
  1063.     return(retVal);
  1064. }
  1065.  
  1066.  
  1067. /*
  1068.  * ----------------------------------------------------------------------------
  1069.  *
  1070.  * MachKernelExceptionHandler --
  1071.  *
  1072.  *      Handle a kernel exception.
  1073.  *
  1074.  * Results:
  1075.  *      MACH_KERN_ERROR if the debugger should be called after this routine 
  1076.  *    returns, MACH_USER_ERROR if a copy to/from user space caused an 
  1077.  *    unrecoverable bus error, and MACH_OK if everything worked out ok.
  1078.  *
  1079.  * Side effects:
  1080.  *      None.
  1081.  *
  1082.  * ----------------------------------------------------------------------------
  1083.  */
  1084. int
  1085. MachKernelExceptionHandler(statusReg, causeReg, badVaddr, pc)
  1086.     unsigned    statusReg;    /* The status register at the time of the
  1087.                  * exception. */
  1088.     unsigned    causeReg;    /* The cause register - contains the type
  1089.                  * of exception. */
  1090.     Address    badVaddr;    /* The address (if any) that the fault
  1091.                  * occured on. */
  1092.     Address    pc;        /* Program counter where to continue. */
  1093. {
  1094.     register    Proc_ControlBlock    *procPtr;
  1095.     ReturnStatus            status;
  1096.     int                    cause;
  1097.  
  1098.     cause = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
  1099.     machBadVaddr = badVaddr;
  1100.  
  1101.     /*
  1102.      * Process kernel traps.
  1103.      */
  1104.     procPtr = Proc_GetActualProc();
  1105.     switch (cause) {
  1106.     case MACH_EXC_INT:
  1107.         status = Interrupt(statusReg, causeReg, pc);
  1108.         return(status);
  1109.     case MACH_EXC_TLB_LD_MISS:
  1110.     case MACH_EXC_TLB_ST_MISS:
  1111.     case MACH_EXC_TLB_MOD: {
  1112.         Boolean    copyInProgress = FALSE;
  1113.  
  1114.         if (statusReg & MACH_SR_INT_ENA_PREV) {
  1115.         /*
  1116.          * Enable interrupts.
  1117.          */
  1118.         Mach_EnableIntr();
  1119.         }
  1120.  
  1121.         if (pc >= F_TO_A Vm_CopyIn && pc < F_TO_A VmMachCopyEnd) {
  1122.         copyInProgress = TRUE;
  1123.         } else if (pc >= F_TO_A MachFetchArgs &&
  1124.                    pc <= F_TO_A MachFetchArgsEnd) {
  1125.         copyInProgress = TRUE;
  1126.         } else if (badVaddr < (Address)VMMACH_VIRT_CACHED_START &&
  1127.                (badVaddr >= (Address)VMMACH_PHYS_CACHED_START ||
  1128.             procPtr == (Proc_ControlBlock *)NIL ||
  1129.             procPtr->vmPtr->numMakeAcc == 0)) {
  1130.         if (procPtr != (Proc_ControlBlock *)NIL) {
  1131.             printf("%s: note: procPtr->vmPtr->numMakeAcc = %d\n", 
  1132.                "MachKernelExceptionHandler",
  1133.                procPtr->vmPtr->numMakeAcc);
  1134.         }
  1135.         return(MACH_KERN_ERROR);
  1136.         }
  1137.         if (((causeReg & MACH_CR_EXC_CODE) >> 
  1138.             MACH_CR_EXC_CODE_SHIFT) == MACH_EXC_TLB_MOD) {
  1139.         status = VmMach_TLBModFault(badVaddr);
  1140.         } else {
  1141.         status = VmMach_TLBFault(badVaddr);
  1142.         }
  1143.         if (status != SUCCESS) {
  1144.         if (copyInProgress) {
  1145.             return(MACH_USER_ERROR);
  1146.         } else {
  1147.             printf("badVaddr = 0x%x\n", badVaddr);
  1148.             return(MACH_KERN_ERROR);
  1149.         }
  1150.         } else {
  1151.         return(MACH_OK);
  1152.         }
  1153.     }
  1154.  
  1155.     case MACH_EXC_ADDR_ERR_LD:
  1156.         printf("MachKernelExceptionHandler: %s: addr: %x PC: %x\n",
  1157.             "Address error on load", badVaddr, pc);
  1158.         return(MACH_KERN_ERROR);
  1159.     case MACH_EXC_ADDR_ERR_ST:
  1160.         printf("MachKernelExceptionHandler:  Address error on store\n");
  1161.         return(MACH_KERN_ERROR);
  1162.     case MACH_EXC_BUS_ERR_IFETCH:
  1163.         printf("MachKernelExceptionHandler:  Bus error on ifetch\n");
  1164.         return(MACH_KERN_ERROR);
  1165.     case MACH_EXC_BUS_ERR_LD_ST:
  1166.         if (pc >= F_TO_A Mach_Probe &&
  1167.             pc <= F_TO_A MachProbeEnd) {
  1168.         return(MACH_USER_ERROR);
  1169.         }
  1170.         printf("MachKernelExceptionHandler:  Bus error on load or store\n");
  1171.         return(MACH_KERN_ERROR);
  1172.     case MACH_EXC_SYSCALL:
  1173.         printf("MachKernelExceptionHandler:  System call in kernel mode\n");
  1174.         return(MACH_KERN_ERROR);
  1175.     case MACH_EXC_BREAK:
  1176.         return(MACH_KERN_ERROR);
  1177.     case MACH_EXC_RES_INST:
  1178.         printf("MachKernelExceptionHandler:  Reserved instruction\n");
  1179.         return(MACH_KERN_ERROR);
  1180.     case MACH_EXC_COP_UNUSABLE:
  1181.         printf("MachKernelExceptionHandler:  Coprocessor unusable\n");
  1182.         return(MACH_KERN_ERROR);
  1183.     case MACH_EXC_OVFLOW:
  1184.         printf("MachKernelExceptionHandler:  Overflow\n");
  1185.         return(MACH_KERN_ERROR);
  1186.     default:
  1187.         printf("MachKernelExceptionHandler: Unknown exception\n");
  1188.         return(MACH_KERN_ERROR);
  1189.     }
  1190. }
  1191.  
  1192.  
  1193. /*
  1194.  * ----------------------------------------------------------------------------
  1195.  *
  1196.  * Interrupt --
  1197.  *
  1198.  *      Call the proper interrupt handler for the given interrupt.
  1199.  *
  1200.  * Results:
  1201.  *      MACH_KERN_ERROR if the machine should go into the debugger, or MACH_OK
  1202.  *    otherwise.
  1203.  *
  1204.  * Side effects:
  1205.  *      None.
  1206.  *
  1207.  * ----------------------------------------------------------------------------
  1208.  */
  1209. #define DEBUG_INTR
  1210. #ifdef DEBUG_INTR
  1211. static int lastInterruptCalled = -1;
  1212. #endif  /* DEBUG_INTR */
  1213.  
  1214.  
  1215. static ReturnStatus
  1216. Interrupt(statusReg, causeReg, pc)
  1217.     unsigned    statusReg;
  1218.     unsigned    causeReg;
  1219.     Address    pc;
  1220. {
  1221.     int        n;
  1222.     unsigned    mask;
  1223.  
  1224. #ifdef DEBUG_INTR
  1225.     if (mach_AtInterruptLevel) {
  1226.     printf("Received interrupt while at interrupt level.\n");
  1227.     }
  1228.     if (mach_NumDisableIntrsPtr[0] > 0) {
  1229.     printf("Received interrupt with mach_NumDisableIntrsPtr[0] = %d.\n",
  1230.            mach_NumDisableIntrsPtr[0]);
  1231.     }
  1232. #endif /* DEBUG_INTR */
  1233.     
  1234.     mach_KernelMode = !(statusReg & MACH_SR_KU_PREV);
  1235.     mach_AtInterruptLevel = 1;
  1236.     n = 0;
  1237.     mask = (causeReg & statusReg & MACH_CR_INT_PENDING) >> 
  1238.                         MACH_CR_HARD_INT_SHIFT;
  1239.     while (mask != 0) {
  1240.     if (mask & 1) {
  1241. #ifdef DEBUG_INTR
  1242.         if (n >= MACH_NUM_HARD_INTERRUPTS) {
  1243.         printf("Bogus index (%d) for interrupt handler\n", n);
  1244.         mach_AtInterruptLevel = 0;
  1245.         return(MACH_KERN_ERROR);
  1246.         }
  1247.         lastInterruptCalled = n;
  1248. #endif /* DEBUG_INTR */
  1249.     /*
  1250.      * Interrupt 5, the FPU interrupt, requires the status, cause, and pc.
  1251.      * These values may have changed in the registers, during a call to
  1252.      * another interrupt handler, so we have to hand the routine the original
  1253.      * values.
  1254.      *
  1255.      * Interrupt 3, the timer interrupt, requires this stuff too, so it
  1256.      * can record the pc for profiling.
  1257.      */
  1258.         if (n == 3 || n==5) {
  1259.         machInterruptRoutines[n](statusReg, causeReg, pc);
  1260.         } else {
  1261.         machInterruptRoutines[n](machInterruptArgs[n]);
  1262.         }
  1263.     }
  1264.     mask >>= 1;
  1265.     n++;
  1266.     }
  1267.  
  1268.     mach_AtInterruptLevel = 0;
  1269. #ifdef DEBUG_INTR
  1270.     lastInterruptCalled = -1;
  1271. #endif /* DEBUG_INTR */
  1272.     return(MACH_OK);
  1273. }
  1274.  
  1275. /*
  1276.  * ----------------------------------------------------------------------------
  1277.  *
  1278.  * MachUserReturn --
  1279.  *
  1280.  *      Take the proper action to return from a user exception.
  1281.  *
  1282.  * Results:
  1283.  *      None.
  1284.  *
  1285.  * Side effects:
  1286.  *      Interrupts disabled.
  1287.  *
  1288.  * ----------------------------------------------------------------------------
  1289.  */
  1290. Boolean
  1291. MachUserReturn(procPtr)
  1292.     register    Proc_ControlBlock    *procPtr;
  1293. {
  1294.     SignalStack    sigStack;
  1295.     Address    pc;
  1296.     int        restarted = 0;
  1297.     Address    savePC;
  1298.  
  1299.  
  1300.     if (procPtr->Prof_Scale >= 2 && procPtr->Prof_PC != 0) {
  1301.     Prof_RecordPC(procPtr);
  1302.     }
  1303.  
  1304.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1305.         procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1306.     printf("UnixProgress = %d entering MachUserReturn\n",
  1307.         procPtr->unixProgress);
  1308.     }
  1309.  
  1310.     /* 
  1311.      * Take a context switch if one is pending for this process.
  1312.      */
  1313.     if (procPtr->schedFlags & SCHED_CONTEXT_SWITCH_PENDING) {
  1314.     Sched_LockAndSwitch();
  1315.     }
  1316.  
  1317.     while (TRUE) {
  1318.     /*
  1319.      * See if we are supposed to single-step this process.  If so
  1320.      * put a break in the proper place.  Don't worry if we miss a signal
  1321.      * because we will be back in real soon anyway (after one instruction).
  1322.      */
  1323.     if (procPtr->genFlags & PROC_SINGLE_STEP_FLAG) {
  1324.         Address        breakPC;
  1325.         unsigned        breakInst;
  1326.         ReturnStatus    status;
  1327.         int            accLen;
  1328.         Address        newAddr;
  1329.  
  1330.         if (machFPCurStatePtr == machCurStatePtr) {
  1331.         MachGetCurFPState(machCurStatePtr);
  1332.         }
  1333.         Vm_MakeAccessible(VM_READONLY_ACCESS, sizeof(Address),
  1334.                   machCurStatePtr->userState.regState.pc, 
  1335.                   &accLen, &newAddr);
  1336.         if (accLen != sizeof(Address)) {
  1337.         printf("MachUserReturn: Can't fetch user's trap PC\n");
  1338.         break;
  1339.         }
  1340.         breakPC = (Address)
  1341.             MachEmulateBranch(machCurStatePtr->userState.regState.regs,
  1342.                       machCurStatePtr->userState.regState.pc,
  1343.                  machCurStatePtr->userState.regState.fpStatusReg,
  1344.                          TRUE);
  1345.         Vm_MakeUnaccessible(newAddr, sizeof(Address));
  1346.         if (Vm_CopyIn(4, breakPC,
  1347.               (Address)&machCurStatePtr->sstepInst) != SUCCESS) {
  1348.         printf("Bad single-step address\n");
  1349.         } else {
  1350.         breakInst = MACH_SSTEP_VAL | 0xd;
  1351.         Vm_ChangeCodeProt(procPtr, breakPC, 4, TRUE);
  1352.         status = Vm_CopyOut(4, (Address)&breakInst, breakPC);
  1353.         Vm_ChangeCodeProt(procPtr, breakPC, 4, FALSE);
  1354.         Vm_FlushCode(procPtr, breakPC, 4);
  1355.         if (status != SUCCESS) {
  1356.             printf("Bad single-step address\n");
  1357.         }
  1358.         }
  1359.         procPtr->genFlags &= ~PROC_SINGLE_STEP_FLAG;
  1360.         Mach_DisableIntr();
  1361.         break;
  1362.     } else {
  1363.         if (procPtr->unixProgress == PROC_PROGRESS_RESTART ||
  1364.             procPtr->unixProgress > 0) {
  1365.         /*
  1366.          * If we received a normal signal, we want to restart
  1367.          * the system call when we leave.
  1368.          * If we received a migrate signal, we will get here on
  1369.          * the new machine.
  1370.          */
  1371.  
  1372.         /*
  1373.          * Mangle the PC so we restart the trap after we leave
  1374.          * the kernel.
  1375.          */
  1376.         restarted = 1;
  1377.         if (debugProcStubs) {
  1378.             printf("Restarting system call with progress %d\n",
  1379.                 procPtr->unixProgress);
  1380.         }
  1381.         }
  1382.         /*
  1383.          * Disable interrupts.  Note that we don't use the DISABLE_INTR 
  1384.          * macro because it increments the nesting depth of interrupts
  1385.          * which we don't want because there is an implicit enable
  1386.          * interrupts on rte.
  1387.          */
  1388.         Mach_DisableIntr();
  1389.         if (!Sig_Pending(procPtr)) {
  1390.         break;
  1391.         }
  1392.         Mach_EnableIntr();
  1393.         savePC = machCurStatePtr->userState.regState.pc;
  1394.         if (restarted) {
  1395.         /*
  1396.          * We have to move the PC now so the migrated process
  1397.          * will start in the right place.
  1398.          * If we don't migrate, we put the PC back after the
  1399.          * Sig_Handle.
  1400.          */
  1401.         machCurStatePtr->userState.regState.pc -= 4;
  1402.         }
  1403.         sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1404.         if (Sig_Handle(procPtr, &sigStack.sigStack, &pc)) {
  1405.         SetupSigHandler(procPtr, &sigStack, pc);
  1406.         Mach_DisableIntr();
  1407.         break;
  1408.         } else {
  1409.         if (procPtr->unixProgress == PROC_PROGRESS_MIG_RESTART ||
  1410.             procPtr->unixProgress == PROC_PROGRESS_RESTART) {
  1411.             restarted = 1;
  1412.             if (debugProcStubs) {
  1413.             printf("No signal action, so we restarted call\n");
  1414.             }
  1415.         } else if (restarted && debugProcStubs) {
  1416.             printf("No signal, yet we restarted system call!\n");
  1417.         }
  1418.         }
  1419.         /*
  1420.          * Restore PC if we didn't migrate.
  1421.          */
  1422.         machCurStatePtr->userState.regState.pc = savePC;
  1423.     }
  1424.     }
  1425.     
  1426.     /*
  1427.      * It is possible for Sig_Handle to mask the migration signal
  1428.      * if a process is not in a state where it can be migrated.
  1429.      * As soon as we return to user mode, though, we will allow migration.
  1430.      */
  1431.     Sig_AllowMigration(procPtr);
  1432.  
  1433.     if (restarted) {
  1434.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1435.     if (debugProcStubs) {
  1436.         printf("Moving the PC to restart the system call\n");
  1437.         printf("Our PC = %x\n",
  1438.             machCurStatePtr->userState.regState.pc);
  1439.     }
  1440.     machCurStatePtr->userState.regState.pc -= 4;
  1441.     if (debugProcStubs) {
  1442.         printf("Now our PC = %x\n",
  1443.             machCurStatePtr->userState.regState.pc);
  1444.         printf("V0 was %d and our call was %d\n", 
  1445.             machCurStatePtr->userState.regState.regs[V0],
  1446.             machCurStatePtr->userState.unixRetVal);
  1447.         printf("Our incoming a0-a3 were %x %x %x %x\n", 
  1448.             machCurStatePtr->userState.regState.regs[A0],
  1449.             machCurStatePtr->userState.regState.regs[A1],
  1450.             machCurStatePtr->userState.regState.regs[A2],
  1451.             machCurStatePtr->userState.regState.regs[A3]);
  1452.     }
  1453.     /*
  1454.      * Our V0 and A3 will have been clobbered by the system call, so
  1455.      * we have to restore them.
  1456.      */
  1457.     machCurStatePtr->userState.regState.regs[V0] =
  1458.         machCurStatePtr->userState.savedV0;
  1459.     machCurStatePtr->userState.regState.regs[A3] =
  1460.         machCurStatePtr->userState.savedA3;
  1461.     }
  1462.  
  1463.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1464.         procPtr->unixProgress != PROC_PROGRESS_UNIX) {
  1465.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1466.     if (debugProcStubs) {
  1467.         printf("UnixProgress = %d leaving MachUserReturn!\n",
  1468.             procPtr->unixProgress);
  1469.     }
  1470.     }
  1471.  
  1472.     return(machFPCurStatePtr == machCurStatePtr);
  1473. }
  1474.  
  1475.  
  1476. /*
  1477.  * ----------------------------------------------------------------------------
  1478.  *
  1479.  * Routines to set up and return from signal handlers.
  1480.  *
  1481.  * In order to call a handler four things must be done:
  1482.  *
  1483.  *    1) The current state of the process must be saved so that when
  1484.  *       the handler returns a normal return to user space can occur.
  1485.  *    2) The user stack must be set up so that the signal number and the
  1486.  *       the signal code are passed to the handler.
  1487.  *    3) Things must be set up so that when the handler returns it returns
  1488.  *       back into the kernel so that state can be cleaned up.
  1489.  *    4) The trap stack that was created when the kernel was entered and is
  1490.  *       used to return a process to user space must be modified so that
  1491.  *       the signal handler is called instead of executing the
  1492.  *       normal return.
  1493.  *
  1494.  * The last one is done by simply changing the program counter where the
  1495.  * user process will execute on return to be the address of the signal
  1496.  * handler and the user stack pointer to point to the proper place on
  1497.  * the user stack.  The first three of these are accomplished by 
  1498.  * setting up the user's registers properly.  The return address register is the
  1499.  * return address where the handler will start executing upon return.  But 
  1500.  * this is just the address of a trap instruction that is stored on the stack
  1501.  * below.  Thus when a handler returns it will execute a trap instruction 
  1502.  * and drop back into the kernel. 
  1503.  */
  1504.  
  1505.  
  1506. /*
  1507.  * ----------------------------------------------------------------------------
  1508.  *
  1509.  * SetupSigHandler --
  1510.  *
  1511.  *      Save machine state on the users stack and set up the exception stack
  1512.  *    so that the user will call the signal handler on return. In order to
  1513.  * Results:
  1514.  *      None.
  1515.  *
  1516.  * Side effects:
  1517.  *      Signal stack set up and saved.
  1518.  *
  1519.  * ----------------------------------------------------------------------------
  1520.  */
  1521. static void
  1522. SetupSigHandler(procPtr, sigStackPtr, pc)
  1523.     register    Proc_ControlBlock    *procPtr;
  1524.     register    SignalStack        *sigStackPtr;
  1525.     Address                pc;
  1526. {
  1527.     Mach_UserState    *userStatePtr;
  1528.     unsigned        usp;
  1529.  
  1530.     userStatePtr = &procPtr->machStatePtr->userState;
  1531.     usp = userStatePtr->regState.regs[SP] - sizeof(Sig_Context) - 
  1532.       MACH_STAND_FRAME_SIZE;
  1533.  
  1534.     sigStackPtr->sigContext.machContext.break1Inst = 0x1000d;
  1535.     /*
  1536.      * Copy the user state onto the signal stack.
  1537.      */
  1538.     bcopy((Address)userStatePtr,
  1539.           (Address)&(sigStackPtr->sigContext.machContext.userState),
  1540.           sizeof(Mach_UserState));
  1541.     /*
  1542.      * Copy over the floating point state.
  1543.      */
  1544.     if (machFPCurStatePtr == machCurStatePtr) {
  1545.     MachGetCurFPState(machCurStatePtr);
  1546.     }
  1547.     bcopy((Address)procPtr->machStatePtr->userState.regState.fpRegs,
  1548.       (Address)sigStackPtr->sigContext.machContext.fpRegs,
  1549.       MACH_NUM_FPRS * sizeof(int));
  1550.     sigStackPtr->sigContext.machContext.fpStatusReg =
  1551.             procPtr->machStatePtr->userState.regState.fpStatusReg;
  1552.     /*
  1553.      * Copy the stack out to user space.
  1554.      */
  1555.     if (Vm_CopyOut(sizeof(Sig_Context), (Address)&sigStackPtr->sigContext,
  1556.             (Address)(usp + MACH_STAND_FRAME_SIZE)) != SUCCESS) {
  1557.         printf("Warning: HandleSig: No room on stack for signal, PID=%x.\n",
  1558.                   procPtr->processID);
  1559.         Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1560.     }
  1561.     /*
  1562.      * Now set up the registers correctly.
  1563.      */
  1564.     userStatePtr->regState.regs[SP] = usp;
  1565.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX) {
  1566.     int unixSignal;
  1567.     if (Compat_SpriteSignalToUnix(sigStackPtr->sigStack.sigNum,
  1568.         &unixSignal) != SUCCESS) {
  1569.         printf("Signal %d invalid in SetupSigHandler\n",
  1570.             sigStackPtr->sigStack.sigNum);
  1571.     } else {
  1572.         userStatePtr->regState.regs[A0] = unixSignal;
  1573.     }
  1574.     } else {
  1575.     userStatePtr->regState.regs[A0] = sigStackPtr->sigStack.sigNum;
  1576.     }
  1577.     userStatePtr->regState.regs[A1] = sigStackPtr->sigStack.sigCode;
  1578.     userStatePtr->regState.regs[A2] = usp + MACH_STAND_FRAME_SIZE;
  1579.     userStatePtr->regState.regs[A3] = sigStackPtr->sigStack.sigAddr;
  1580.     userStatePtr->regState.pc = pc;
  1581.     userStatePtr->regState.regs[RA] = usp + MACH_STAND_FRAME_SIZE + 
  1582.         (unsigned)&((Sig_Context *)0)->machContext.break1Inst;
  1583. }
  1584.  
  1585.  
  1586. /*
  1587.  * ----------------------------------------------------------------------------
  1588.  *
  1589.  * ReturnFromSigHandler --
  1590.  *
  1591.  *      Process a return from a signal handler.
  1592.  *    
  1593.  * Results:
  1594.  *      None.
  1595.  *
  1596.  * Side effects:
  1597.  *      Signal stack struct and size filled in the machine struct for the
  1598.  *    given process.
  1599.  *
  1600.  * ----------------------------------------------------------------------------
  1601.  */
  1602. static void
  1603. ReturnFromSigHandler(procPtr)
  1604.     register    Proc_ControlBlock    *procPtr;
  1605. {
  1606.     register    Mach_State    *statePtr;
  1607.     SignalStack            sigStack;
  1608.  
  1609.     statePtr = procPtr->machStatePtr;
  1610.     /*
  1611.      * Copy the signal stack in.
  1612.      */
  1613.     if (Vm_CopyIn(sizeof(Sig_Context),
  1614.           (Address)(statePtr->userState.regState.regs[SP] + 
  1615.                 MACH_STAND_FRAME_SIZE),
  1616.           (Address) &sigStack.sigContext) != SUCCESS) {
  1617.     printf("%s Mach_Code: Stack too small to extract trap info, PID=%x.\n",
  1618.         "Warning:", procPtr->processID);
  1619.     Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1620.     }
  1621.     sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1622.     /*
  1623.      * Take the proper action on return from a signal.
  1624.      */
  1625.     Sig_Return(procPtr, &sigStack.sigStack);
  1626.     /*
  1627.      * Restore user state.
  1628.      */
  1629.     bcopy((Address)&sigStack.sigContext.machContext.userState,
  1630.           (Address)&statePtr->userState, sizeof(statePtr->userState));
  1631.     /*
  1632.      * Copy in the floating point state.
  1633.      */
  1634.     bcopy((Address)sigStack.sigContext.machContext.fpRegs,
  1635.       (Address)statePtr->userState.regState.fpRegs,
  1636.       MACH_NUM_FPRS * sizeof(int));
  1637.     statePtr->userState.regState.fpStatusReg = 
  1638.     sigStack.sigContext.machContext.fpStatusReg & ~MACH_FPC_EXCEPTION_BITS;
  1639.     if (machFPCurStatePtr == machCurStatePtr) {
  1640.     machFPCurStatePtr = (Mach_State *)NIL;
  1641.     }
  1642. }
  1643.  
  1644.  
  1645. /*
  1646.  * ----------------------------------------------------------------------------
  1647.  *
  1648.  * Mach_ProcessorState --
  1649.  *
  1650.  *    Determines what state the processor is in.
  1651.  *
  1652.  * Results:
  1653.  *    MACH_USER    if was at user level
  1654.  *    MACH_KERNEL    if was at kernel level
  1655.  *
  1656.  * Side effects:
  1657.  *    None.
  1658.  *
  1659.  * ----------------------------------------------------------------------------
  1660.  */
  1661. /*ARGSUSED*/
  1662. Mach_ProcessorStates 
  1663. Mach_ProcessorState(processor)
  1664.     int processor;    /* processor number for which info is requested */
  1665. {
  1666.     if (mach_KernelMode) {
  1667.     return(MACH_KERNEL);
  1668.     } else {
  1669.     return(MACH_USER);
  1670.     }
  1671. }
  1672.  
  1673.  
  1674. /*
  1675.  * ----------------------------------------------------------------------------
  1676.  *
  1677.  * Mach_GetMachineArch --
  1678.  *
  1679.  *    Return the machine architecture.
  1680.  *
  1681.  * Results:
  1682.  *    The machine architecture.
  1683.  *
  1684.  * Side effects:
  1685.  *    None.
  1686.  *
  1687.  * ----------------------------------------------------------------------------
  1688.  */
  1689. int
  1690. Mach_GetMachineArch()
  1691. {
  1692.     return SYS_DS3100;
  1693. }
  1694.  
  1695.  
  1696. /*
  1697.  * ----------------------------------------------------------------------------
  1698.  *
  1699.  * Mach_GetMachineType --
  1700.  *
  1701.  *    Return the machine type.
  1702.  *
  1703.  * Results:
  1704.  *    0.
  1705.  *
  1706.  * Side effects:
  1707.  *    None.
  1708.  *
  1709.  * ----------------------------------------------------------------------------
  1710.  */
  1711. int
  1712. Mach_GetMachineType()
  1713. {
  1714.     return 0;
  1715. }
  1716.  
  1717.  
  1718. /*
  1719.  * ----------------------------------------------------------------------------
  1720.  *
  1721.  *  Mach_CheckSpecialHandling--
  1722.  *
  1723.  *    Forces a processor to check the special handling flag of a process.
  1724.  *    This should only be called on a multiprocessor.
  1725.  *
  1726.  * Results:
  1727.  *    None.
  1728.  *
  1729.  * Side effects:
  1730.  *    None.
  1731.  *
  1732.  * ----------------------------------------------------------------------------
  1733.  */
  1734. void
  1735. Mach_CheckSpecialHandling(pnum)
  1736.     int        pnum;        /* Processor number. */
  1737. {
  1738.     panic("Mach_CheckSpecialHandling called for processor %d\n",pnum);
  1739. }
  1740.  
  1741.  
  1742. /*
  1743.  *----------------------------------------------------------------------
  1744.  *
  1745.  * Mach_GetNumProcessors() --
  1746.  *
  1747.  *    Return the number of processors in the system.  NOTE: This should
  1748.  *    really be in a machine-independent area of the mach module.  Note
  1749.  *    further: if this is used only as a system call, it should return
  1750.  *    a ReturnStatus!
  1751.  *
  1752.  * Results:
  1753.  *    The number of processors is returned.  
  1754.  *
  1755.  * Side effects:
  1756.  *    None
  1757.  *
  1758.  *----------------------------------------------------------------------
  1759.  */
  1760.  
  1761. int
  1762. Mach_GetNumProcessors()
  1763. {
  1764.     return (mach_NumProcessors);
  1765. }
  1766.  
  1767.  
  1768. /*
  1769.  *----------------------------------------------------------------------
  1770.  *
  1771.  * Mach_GetBootArgs --
  1772.  *
  1773.  *    Returns the arguments out of the boot parameter structure. 
  1774.  *
  1775.  * Results:
  1776.  *    Number of elements returned in argv.
  1777.  *
  1778.  * Side effects:
  1779.  *    None.
  1780.  *
  1781.  *----------------------------------------------------------------------
  1782.  */
  1783. /*ARGSUSED*/
  1784. int
  1785. Mach_GetBootArgs(argc, bufferSize, argv, buffer)
  1786.     int    argc;            /* Number of elements in argv */
  1787.     int    bufferSize;        /* Size of buffer */
  1788.     char    **argv;            /* Ptr to array of arg pointers */
  1789.     char    *buffer;        /* Storage for arguments */
  1790. {
  1791.     int        i;
  1792.     int        offset;
  1793.  
  1794.     bcopy(machMonBootParam.strings, buffer, 
  1795.       (bufferSize < 256) ? bufferSize : 256);
  1796.     offset = (int) machMonBootParam.strings - (int) buffer;
  1797.     for(i = 0; i < argc; i++) {
  1798.     if (machMonBootParam.argPtr[i] == (char *)NULL) break;
  1799.     argv[i] = (char *) (machMonBootParam.argPtr[i] - (char *) offset);
  1800.     }
  1801.     return i;
  1802. }
  1803.  
  1804. /*
  1805.  *----------------------------------------------------------------------
  1806.  *
  1807.  * Mach_GetEtherAddress --
  1808.  *
  1809.  *    Return the ethernet address out of the rom.
  1810.  *
  1811.  * Results:
  1812.  *    Number of elements returned in argv.
  1813.  *
  1814.  * Side effects:
  1815.  *    *etherAddrPtr gets the ethernet address.
  1816.  *
  1817.  *----------------------------------------------------------------------
  1818.  */
  1819. void
  1820. Mach_GetEtherAddress(etherAddrPtr)
  1821.     Net_EtherAddress    *etherAddrPtr;
  1822. {
  1823.     volatile unsigned    *romPtr = (unsigned *)0xBD000000;
  1824.  
  1825.     etherAddrPtr->byte1 = (romPtr[0] >> 8) & 0xff;
  1826.     etherAddrPtr->byte2 = (romPtr[1] >> 8) & 0xff;
  1827.     etherAddrPtr->byte3 = (romPtr[2] >> 8) & 0xff;
  1828.     etherAddrPtr->byte4 = (romPtr[3] >> 8) & 0xff;
  1829.     etherAddrPtr->byte5 = (romPtr[4] >> 8) & 0xff;
  1830.     etherAddrPtr->byte6 = (romPtr[5] >> 8) & 0xff;
  1831. }
  1832.  
  1833.  
  1834. /*
  1835.  *----------------------------------------------------------------------
  1836.  *
  1837.  * MemErrorInterrupt --
  1838.  *
  1839.  *    Handler an interrupt for the DZ device.
  1840.  *
  1841.  * Results:
  1842.  *    None.
  1843.  *
  1844.  * Side effects:
  1845.  *    None.
  1846.  *
  1847.  *----------------------------------------------------------------------
  1848.  */
  1849. static void
  1850. MemErrorInterrupt()
  1851. {
  1852.     unsigned short *sysCSRPtr = (unsigned short *)0xbe000000;
  1853.     unsigned short csr;
  1854.  
  1855.     csr = *sysCSRPtr;
  1856.  
  1857.     if (csr & MACH_CSR_MEM_ERR) {
  1858.     panic("Mem error interrupt\n");
  1859.     } else {
  1860.     *sysCSRPtr = MACH_CSR_VINT | csr | 0x00ff;
  1861.     }
  1862. }
  1863.  
  1864.  
  1865. /*
  1866.  *----------------------------------------------------------------------
  1867.  *
  1868.  * Mach_FlushCode --
  1869.  *
  1870.  *    Flush the kernel code from the icache at the given address.
  1871.  *
  1872.  * Results:
  1873.  *    None.
  1874.  *
  1875.  * Side effects:
  1876.  *    None.
  1877.  *
  1878.  *----------------------------------------------------------------------
  1879.  */
  1880. void
  1881. Mach_FlushCode(addr, len) 
  1882.     Address    addr;
  1883.     unsigned    len;
  1884. {
  1885.     unsigned cacheAddr;
  1886.  
  1887.     cacheAddr = VMMACH_PHYS_UNCACHED_START - machInstCacheSize +  
  1888.         ((unsigned)addr & (machInstCacheSize - 1));
  1889. #ifdef notdef
  1890.     printf("len=%d addr=%x cacheAddr=%x\n", len, addr, cacheAddr);
  1891. #endif
  1892.     MachCleanICache(cacheAddr, len);
  1893. }
  1894.  
  1895.  
  1896. /*
  1897.  *----------------------------------------------------------------------
  1898.  *
  1899.  * Mach_SendSignal
  1900.  *
  1901.  *    Send either an illegal instruction or a floating point exception
  1902.  *    to the current process.
  1903.  *
  1904.  * Results:
  1905.  *    None.
  1906.  *
  1907.  * Side effects:
  1908.  *    None.
  1909.  *
  1910.  *----------------------------------------------------------------------
  1911.  */
  1912. void
  1913. Mach_SendSignal(sigType)
  1914.     int    sigType;
  1915. {
  1916.     Proc_ControlBlock    *procPtr;
  1917.  
  1918.     procPtr = Proc_GetActualProc();
  1919.  
  1920.     printf("Mach_SendSignal: Sending signal\n");
  1921.  
  1922.     switch ((int)sigType) {
  1923.     case MACH_SIGFPE:
  1924.         (void) Sig_Send(SIG_ILL_INST, SIG_FP_EXCEPTION,
  1925.                 procPtr->processID, FALSE, (Address)0);
  1926.         break;
  1927.     case MACH_SIGILL:
  1928.         (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1929.                 procPtr->processID, FALSE, (Address)0);
  1930.         break;
  1931.     default:
  1932.         panic("Mach_SendSignal: Bad signal type\n");
  1933.         break;
  1934.     }
  1935. }
  1936.  
  1937. void
  1938. PrintError()
  1939. {
  1940.     panic("Error on stack\n");
  1941. }
  1942.  
  1943. static void
  1944. PrintInst(pc, inst)
  1945.     unsigned pc;
  1946.     unsigned inst;
  1947. {
  1948.     printf("Emulating 0x%x: 0x%x\n", pc, inst);
  1949. }
  1950.  
  1951. static void
  1952. SoftFPReturn()
  1953. {
  1954.     printf("SoftFPReturn\n");
  1955. }
  1956.  
  1957. /*
  1958.  *----------------------------------------------------------------------
  1959.  *
  1960.  * Mach_SigreturnStub --
  1961.  *
  1962.  *    Procedure to map from Unix sigreturn system call to Sprite.
  1963.  *    On the decstation, this is used for returning from a signal.
  1964.  *    Note: This routine is exactly the same as MachUNIXLongJumpReturn.
  1965.  *    Presumably the other routine will go away as soon as Unix
  1966.  *    compatibility is working.
  1967.  *
  1968.  * Results:
  1969.  *    Error code is returned upon error.  Otherwise SUCCESS is returned.
  1970.  *
  1971.  * Side effects:
  1972.  *    Side effects associated with the system call.
  1973.  *
  1974.  *----------------------------------------------------------------------
  1975.  */
  1976. int
  1977. Mach_SigreturnStub(sigContextPtr)
  1978.     struct sigcontext *sigContextPtr;
  1979. {
  1980.     struct sigcontext    sigContext;
  1981.     Mach_RegState    *regsPtr;
  1982.     int            dummy;
  1983.     ReturnStatus    status;
  1984.     extern Mach_State   *machCurStatePtr;
  1985.  
  1986.     status = Vm_CopyIn(sizeof(struct sigcontext), (Address)sigContextPtr,
  1987.                (Address)&sigContext);
  1988.     if (status != SUCCESS) {
  1989.     return(status);
  1990.     }
  1991.     regsPtr = &machCurStatePtr->userState.regState;
  1992.     regsPtr->pc = (Address)(sigContext.sc_pc - 4);
  1993.     bcopy(sigContext.sc_regs, regsPtr->regs, sizeof(sigContext.sc_regs));
  1994.     regsPtr->mflo = sigContext.sc_mdlo;
  1995.     regsPtr->mfhi = sigContext.sc_mdhi;
  1996.     bcopy(sigContext.sc_fpregs, regsPtr->fpRegs, sizeof(sigContext.sc_fpregs));
  1997.     regsPtr->fpStatusReg = sigContext.sc_fpc_csr;
  1998.     Proc_GetCurrentProc()->sigHoldMask = sigContext.sc_mask;
  1999.     return(SUCCESS);
  2000. }
  2001.  
  2002. /*
  2003.  *----------------------------------------------------------------------
  2004.  *
  2005.  * CheckFastRestart --
  2006.  *
  2007.  *    Check if enough space was allocated for the fast restart.
  2008.  *
  2009.  * Results:
  2010.  *    None.
  2011.  *
  2012.  * Side effects:
  2013.  *    None.
  2014.  *
  2015.  *----------------------------------------------------------------------
  2016.  */
  2017. static void
  2018. CheckFastRestart()
  2019. {
  2020.     /* No-op on decstations for now. */
  2021.     return;
  2022. }
  2023.  
  2024.  
  2025. /*
  2026.  *----------------------------------------------------------------------
  2027.  *
  2028.  * Mach_GetRestartTableSize --
  2029.  *
  2030.  *    Return the size allocated for the fast restart table area.
  2031.  *
  2032.  * Results:
  2033.  *    None.
  2034.  *
  2035.  * Side effects:
  2036.  *    None.
  2037.  *
  2038.  *----------------------------------------------------------------------
  2039.  */
  2040. int
  2041. Mach_GetRestartTableSize()
  2042. {
  2043.     /* No-op on decstations for now. */
  2044.     return 0;
  2045. }
  2046.  
  2047.  
  2048. /*
  2049.  *----------------------------------------------------------------------
  2050.  *
  2051.  * Mach_FastBoot --
  2052.  *
  2053.  *    Do a fast reboot (using copied initialized data heap, etc.)
  2054.  *
  2055.  * Results:
  2056.  *    FAILURE if we're not set up to do a fast boot.  Otherwise we don't
  2057.  *    return, but boot instead.
  2058.  *
  2059.  * Side effects:
  2060.  *    Will probably cause fast reboot.
  2061.  *
  2062.  *----------------------------------------------------------------------
  2063.  */
  2064. int
  2065. Mach_FastBoot()
  2066. {
  2067.     /* No-op on decstations for now. */
  2068.     Mach_MonPrintf("Can't do decstation fast boot yet.\n");
  2069.     return FAILURE;
  2070. }
  2071.